package com.ums.upos.service;

import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.ScanResult;
import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import com.ums.upos.uapi.ServiceResult;
import com.ums.upos.uapi.network.NetWorkHandler;
import com.ums.upos.uapi.network.NetWorkListener;
import com.ums.upos.uapi.network.NetWorkParams;
import com.ums.upos.uapi.network.NetWorkType;
import com.ums.upos.util.SharedPreferencesUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import rx.Observable;
import rx.Subscriber;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

/**
 * Created by xiaox on 16-03-08.
 */
public class NetWorkBinder extends NetWorkHandler.Stub {
    private final String TAG = "NetWorkService";
    private Context context;
    private Logger log;

    NetWorkBinder(Context context) {
        this.context = context;
        log = LoggerFactory.getLogger(TAG);
    }

    @Override
    public int setNetworkConfig(Bundle bundle) throws RemoteException {
        log.info("call setNetworkConfig");
        if (bundle == null || bundle.size() == 0) return ServiceResult.Param_In_Invalid;
        for (String str : bundle.keySet()) {
            log.debug("key {},value {}", str, bundle.get(str));
        }
        try {
            int networkType = bundle.getInt(NetWorkParams.COMMON_NETWORKTYPE);
            if (networkType == NetWorkType.LAN) {
                boolean isDhcp = bundle.getBoolean(NetWorkParams.LAN_ISDHCP);
                String ip = bundle.getString(NetWorkParams.LAN_LOCAL_IP);
                String mask = bundle.getString(NetWorkParams.LAN_SUBNET_MASK);
                String gate = bundle.getString(NetWorkParams.LAN_NET_GATE);
                String dns1 = bundle.getString(NetWorkParams.LAN_DNS1);
                String dns2 = bundle.getString(NetWorkParams.LAN_DNS2);
                if (!isDhcp) {
                    if (!ipFormat(ip) || !ipFormat(mask) || !ipFormat(gate) || !ipFormat(dns1) || !ipFormat(dns2)) {
                        return ServiceResult.Fail;
                    }
                }
                Intent intent = new Intent("android.intent.action.SETTING_ETHERNET");
                intent.putExtra("dhcp", isDhcp);
                intent.putExtra("ip", ip);
                intent.putExtra("mask", mask);
                intent.putExtra("gate", gate);
                intent.putExtra("dns", dns1);
                //intent.putExtra("domain", bundle.getString(NetWorkParams.LAN_DOMAINNAME));
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
                intent.addFlags(Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
                context.startActivity(intent);
                //log.error("LAN设置完成--");
            } else if (networkType == NetWorkType.GPRS) {

                String apnStr = bundle.getString(NetWorkParams.GPRS_APN)
                        + "|" + bundle.getString(NetWorkParams.GPRS_USERNAME)
                        + "|" + bundle.getString(NetWorkParams.GPRS_PASSWORD);
                log.debug("apnStr:" + apnStr);

                Intent intent = new Intent("android.intent.action.INSERT_HIDE", Uri.parse("content://telephony/carriers"));
                intent.putExtra("apn", bundle.getString(NetWorkParams.GPRS_APN));
                intent.putExtra("username", bundle.getString(NetWorkParams.GPRS_USERNAME));
                intent.putExtra("password", bundle.getString(NetWorkParams.GPRS_PASSWORD));
                intent.putExtra("mcc", "460");

                TelephonyManager telManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
                String imsi = telManager.getSubscriberId();
                if (imsi != null) {
                    if (imsi.startsWith("46000")) {//中国移动TD
                        intent.putExtra("mnc", "00");
                    } else if (imsi.startsWith("46002")) {//中国移动GSM 因为移动网络编号46000下的IMSI已经用完，所以虚拟了一个46002编号，134/159号段使用了此编号 //中国移动
                        intent.putExtra("mnc", "02");
                    } else if (imsi.startsWith("46001")) {//中国联通
                        intent.putExtra("mnc", "01");
                    } else if (imsi.startsWith("46003")) {//中国电信
                        intent.putExtra("mnc", "03");
                    }
                }
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
                context.startActivity(intent);
                SharedPreferencesUtil.getInstance(context).putString("apnStr", apnStr);
                log.debug("GPRS设置完成");
            } else if (networkType == NetWorkType.WIFI) {
                String ssid = bundle.getString(NetWorkParams.WIFI_SSID);
                int authType = bundle.getInt(NetWorkParams.WIFI_AUTHTYPE);
                String pwd = bundle.getString(NetWorkParams.WIFI_PASSWORD);
                boolean isHidden = bundle.getBoolean(NetWorkParams.WIFI_ISHIDDEN);
                boolean isDhcp = bundle.getBoolean(NetWorkParams.WIFI_ISDHCP);
                String localIp = bundle.getString(NetWorkParams.WIFI_LOCAL_IP);
                String gate = bundle.getString(NetWorkParams.WIFI_NET_GATE);
                String dns1 = bundle.getString(NetWorkParams.WIFI_DNS1);
                String dns2 = bundle.getString(NetWorkParams.WIFI_DNS2);
                if (!isDhcp) {
                    if (!ipFormat(localIp) || !ipFormat(gate) || !ipFormat(dns1) || !ipFormat(dns2)) {
                        return ServiceResult.Fail;
                    }
                }
                SharedPreferencesUtil.getInstance(context).putString(NetWorkParams.WIFI_SSID, ssid);
                SharedPreferencesUtil.getInstance(context).putInt(NetWorkParams.WIFI_AUTHTYPE, authType);
                SharedPreferencesUtil.getInstance(context).putString(NetWorkParams.WIFI_PASSWORD, pwd);
                SharedPreferencesUtil.getInstance(context).putBoolean(NetWorkParams.WIFI_ISHIDDEN, isHidden);
                SharedPreferencesUtil.getInstance(context).putBoolean(NetWorkParams.WIFI_ISDHCP, isDhcp);
                SharedPreferencesUtil.getInstance(context).putString(NetWorkParams.WIFI_LOCAL_IP, localIp);
                SharedPreferencesUtil.getInstance(context).putString(NetWorkParams.WIFI_NET_GATE, gate);
                SharedPreferencesUtil.getInstance(context).putString(NetWorkParams.WIFI_DNS1, dns1);
                SharedPreferencesUtil.getInstance(context).putString(NetWorkParams.WIFI_DNS2, dns2);
            } else {
                return ServiceResult.Param_In_Invalid;
            }
            return ServiceResult.Success;
        } catch (Exception e) {
            e.printStackTrace();
            return ServiceResult.Fail;
        }
    }

    @Override
    public boolean open(final int networkType, final NetWorkListener listener) throws RemoteException {
        log.info("call open network: networkType:" + networkType);
        if (listener == null) return false;
        if (networkType != NetWorkType.GPRS && networkType != NetWorkType.LAN && networkType != NetWorkType.WIFI) {
            listener.onOpenResult(ServiceResult.Param_In_Invalid);
            return false;
        }
        Observable.create(new Observable.OnSubscribe<Object>() {
            @Override
            public void call(Subscriber<? super Object> subscriber) {
                if (networkType == NetWorkType.WIFI) {
                    WifiAdmin.getInstance().init(context,
                            SharedPreferencesUtil.getInstance(context).getString(NetWorkParams.WIFI_SSID),
                            SharedPreferencesUtil.getInstance(context).getString(NetWorkParams.WIFI_PASSWORD),
                            SharedPreferencesUtil.getInstance(context).getInt(NetWorkParams.WIFI_AUTHTYPE));
                    if (!(SharedPreferencesUtil.getInstance(context).getBoolean(NetWorkParams.WIFI_ISDHCP))) {
                        log.debug("设置静态IP");
                        WifiAdmin.getInstance().setStaticIp(
                                SharedPreferencesUtil.getInstance(context).getString(NetWorkParams.WIFI_LOCAL_IP),
                                SharedPreferencesUtil.getInstance(context).getString(NetWorkParams.WIFI_NET_GATE),
                                SharedPreferencesUtil.getInstance(context).getString(NetWorkParams.WIFI_DNS1),
                                SharedPreferencesUtil.getInstance(context).getString(NetWorkParams.WIFI_DNS2)
                        );
                    }
                    int wcgID = WifiAdmin.getInstance().addNetwork();
                    log.debug("wcgID:" + wcgID);
                    boolean isSucess = WifiAdmin.getInstance().openWifi(wcgID);
                    if (isSucess) {
                        subscriber.onCompleted();
                    } else {
                        subscriber.onError(new Exception());
                    }
                } else if (networkType == NetWorkType.LAN) {
                    Intent intent = new Intent("android.intent.action.ENABLE_ETHERNET");
                    intent.putExtra("enable", true);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
                    context.startActivity(intent);
                    subscriber.onCompleted();
                } else if (networkType == NetWorkType.GPRS) {
                    try {
                        toggleMobileData(context, true);
                        subscriber.onCompleted();
                    } catch (Exception e) {
                        subscriber.onError(e);
                    }
                }
            }
        })
                .subscribeOn(Schedulers.newThread())
                .subscribe(new Action1<Object>() {
                    @Override
                    public void call(Object o) {

                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        try {
                            listener.onOpenResult(ServiceResult.Fail);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                }, new Action0() {
                    @Override
                    public void call() {
                        try {
                            listener.onOpenResult(ServiceResult.Success);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                });
        return true;
    }


    @Override
    public boolean close(final int networkType, final NetWorkListener listener) throws RemoteException {
        log.info("close network: networkType:" + networkType);
        if (listener == null) return false;
        if (networkType != NetWorkType.GPRS && networkType != NetWorkType.LAN && networkType != NetWorkType.WIFI) {
            listener.onCloseResult(ServiceResult.Param_In_Invalid);
            return false;
        }
        Observable.create(new Observable.OnSubscribe<Object>() {
                              @Override
                              public void call(Subscriber<? super Object> subscriber) {
                                  if (networkType == NetWorkType.LAN) {
                                      Intent intent = new Intent("android.intent.action.ENABLE_ETHERNET");
                                      intent.putExtra("enable", false);
                                      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                      intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
                                      context.startActivity(intent);
                                      subscriber.onCompleted();
                                  } else if (networkType == NetWorkType.WIFI) {
                                      WifiAdmin.getInstance().init(context);
                                      WifiAdmin.getInstance().closeWifi();
                                      subscriber.onCompleted();
                                  } else if (networkType == NetWorkType.GPRS) {
                                      try {
                                          toggleMobileData(context, false);
                                          subscriber.onCompleted();
                                      } catch (Exception e) {
                                          subscriber.onError(e);
                                      }
                                  }
                              }
                          }
        )
                .subscribeOn(Schedulers.newThread())
                .subscribe(new Action1<Object>() {
                    @Override
                    public void call(Object o) {

                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        try {
                            listener.onCloseResult(ServiceResult.Fail);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                }, new Action0() {
                    @Override
                    public void call() {
                        try {
                            listener.onCloseResult(ServiceResult.Success);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                });
        return true;
    }

    private boolean checkNetworkState(Context context) {
        if (context != null) {
            ConnectivityManager mConnectivityManager = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
            //1.判断是否有网络连接
            boolean networkAvailable = networkInfo.isAvailable();
            log.debug("networkAvailable:" + networkAvailable);
            return networkAvailable;
//                //2.获取当前网络连接的类型信息
//                int networkType = networkInfo.getType();
//                if(ConnectivityManager.TYPE_WIFI == networkType){
//                    //当前为wifi网络
//                }else if(ConnectivityManager.TYPE_MOBILE == networkType){
//                    //当前为mobile网络
//                }
        }
        return false;
    }

    @Override
    public void ping(final String serverIp, final int timeout, final NetWorkListener listener) throws RemoteException {
        log.debug("call ping,Ip {}", serverIp);
        if (listener == null) return;
        if (TextUtils.isEmpty(serverIp) || timeout < 0) {
            listener.onPingResult(ServiceResult.Param_In_Invalid);
        }
        Observable.create(new Observable.OnSubscribe<Object>() {
                              @Override
                              public void call(Subscriber<? super Object> subscriber) {
                                  boolean con = checkNetworkState(context);
                                  if (!con) {
                                      log.debug("内络不通");
                                      subscriber.onError(new Exception());
                                      return;
                                  }
                                  try {
                                      Process p = Runtime.getRuntime().exec("ping -c " + 1 + " -w " + timeout / 1000 + " " + serverIp);
                                      int status = p.waitFor();
                                      InputStream input = p.getInputStream();
                                      BufferedReader in = new BufferedReader(new InputStreamReader(input));
                                      StringBuilder buffer = new StringBuilder();
                                      String line;
                                      while ((line = in.readLine()) != null) {
                                          buffer.append(line);
                                      }
                                      log.debug(buffer.toString());
                                      log.debug("ping {}", status == 0 ? "成功" : "失败");
                                      if (status == 0) {
                                          subscriber.onCompleted();
                                      } else {
                                          subscriber.onError(new Exception());
                                      }
                                  } catch (Exception e) {
                                      subscriber.onError(e);
                                  }
                              }
                          }
        )
                .subscribeOn(Schedulers.newThread())
                .subscribe(new Action1<Object>() {
                    @Override
                    public void call(Object o) {

                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        try {
                            listener.onPingResult(ServiceResult.Fail);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                }, new Action0() {
                    @Override
                    public void call() {
                        try {
                            listener.onPingResult(ServiceResult.Success);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                });
    }

    @Override
    public void scanWifi(NetWorkListener listener) throws RemoteException {
        log.debug("call scanWifi");
        if (listener == null) return;
        WifiAdmin.getInstance().init(context);
        String wifiSpotsList = "";
        Bundle wifiSpots = new Bundle();
        WifiAdmin.getInstance().startScan();
        List<ScanResult> list = WifiAdmin.getInstance().getWifiList();
        for (ScanResult wifi : list) {
            log.debug("wifi:" + wifi);
            //wifiSpotsList += ("|" + wifi.SSID);
            wifiSpots.putString(wifi.BSSID, wifi.SSID);

        }
        //wifiSpots.putString(WifiAdmin.getInstance().getMac(), wifiSpotsList);
        listener.onScanWifiResult(ServiceResult.Success, wifiSpots);
    }

    /**
     * 移动网络开关
     */
    private void toggleMobileData(Context context, boolean enabled) throws Exception {
        ConnectivityManager conMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        Class<?> conMgrClass = null; // ConnectivityManager类
        Field iConMgrField = null; // ConnectivityManager类中的字段
        Object iConMgr = null; // IConnectivityManager类的引用
        Class<?> iConMgrClass = null; // IConnectivityManager类
        Method setMobileDataEnabledMethod = null; // setMobileDataEnabled方法

        log.debug("当前系统版SDK版本为：{}", Build.VERSION.SDK_INT);
        if (Build.VERSION.SDK_INT > 20) {
            log.debug("当前系统版本为5.0以上");
            //5.0以上系统
            TelephonyManager telephonyService = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            try {
                setMobileDataEnabledMethod = telephonyService.getClass().getDeclaredMethod("setDataEnabled", boolean.class);
                if (null != setMobileDataEnabledMethod) {
                    setMobileDataEnabledMethod.invoke(telephonyService, enabled);
                }
            } catch (Exception e) {
                log.error("Error setting" + ((InvocationTargetException) e).getTargetException() + telephonyService);
            }
        } else {
            log.debug("当前系统版本为4.4及以下");
            // 取得ConnectivityManager类
            conMgrClass = Class.forName(conMgr.getClass().getName());
            // 取得ConnectivityManager类中的对象mService
            iConMgrField = conMgrClass.getDeclaredField("mService");
            // 设置mService可访问
            iConMgrField.setAccessible(true);
            // 取得mService的实例化类IConnectivityManager
            iConMgr = iConMgrField.get(conMgr);
            // 取得IConnectivityManager类
            iConMgrClass = Class.forName(iConMgr.getClass().getName());
            // 取得IConnectivityManager类中的setMobileDataEnabled(boolean)方法
            setMobileDataEnabledMethod = iConMgrClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
            // 设置setMobileDataEnabled方法可访问
            setMobileDataEnabledMethod.setAccessible(true);
            // 调用setMobileDataEnabled方法
            setMobileDataEnabledMethod.invoke(iConMgr, enabled);
        }
    }

    private boolean ipFormat(String ipAddress) {
        String ip = "([1-9]|[1-9]//d|1//d{2}|2[0-4]//d|25[0-5])(//.(//d|[1-9]//d|1//d{2}|2[0-4]//d|25[0-5])){3}";
        Pattern pattern = Pattern.compile(ip);
        Matcher matcher = pattern.matcher(ipAddress);
        return matcher.matches();
    }
}
